<?php
/**
 * 博客系统核心类
 * 统一处理所有数据库操作和业务逻辑
 * 使用mysqli直连数据库，简化调试和维护
 */

class BlogSystem {
    private $conn;              // 数据库连接
    private $config;            // 系统配置
    private $debug = false;     // 调试模式开关
    
    /**
     * 构造函数 - 初始化数据库连接和配置
     */
    public function __construct() {
        $this->initConfig();
        $this->initDatabase();
        $this->initSession();
    }
    
    /**
     * 初始化系统配置
     * 使用已有的数据库配置文件
     */
    private function initConfig() {
        // 引入现有的数据库配置
        require_once __DIR__ . '/../config/database.php';
        
        $this->config = [
            'db_host' => DB_HOST,           // 使用现有配置
            'db_user' => DB_USER,           // 使用现有配置
            'db_pass' => DB_PASS,           // 使用现有配置
            'db_name' => DB_NAME,           // 使用现有配置
            'base_url' => BASE_URL,         // 使用现有配置
            'posts_per_page' => 5,          // 每页文章数量
            'upload_path' => 'uploads/images/',     // 上传目录（项目根目录下）
            'max_upload_size' => 2 * 1024 * 1024,  // 最大上传文件大小2MB
        ];
    }
    
    /**
     * 初始化数据库连接
     * 使用现有的数据库连接函数getConnection()
     */
    private function initDatabase() {
        // 使用现有的数据库连接函数
        $this->conn = getConnection();
        
        // 检查连接是否成功
        if (!$this->conn) {
            $this->debugOutput("数据库连接失败: " . mysqli_connect_error());
            die("数据库连接失败，请检查配置");
        }
        
        $this->debugOutput("数据库连接成功");
    }
    
    /**
     * 初始化会话
     */
    private function initSession() {
        if (session_status() == PHP_SESSION_NONE) {
            session_start();
        }
    }
    
    /**
     * 调试输出函数
     * @param string $message 调试信息
     * @param string $type 信息类型 (info, error, warning)
     */
    private function debugOutput($message, $type = 'info') {
        if (!$this->debug) return;
        
        $timestamp = date('Y-m-d H:i:s');
        $prefix = '';
        $color = '';
        
        switch ($type) {
            case 'error':
                $prefix = '[ERROR]';
                $color = '#dc3545';
                break;
            case 'warning':
                $prefix = '[WARNING]';
                $color = '#ffc107';
                break;
            default:
                $prefix = '[INFO]';
                $color = '#17a2b8';
        }
        
        // 输出到HTML页面（可见调试信息）
        echo "<div style='background: rgba(0,0,0,0.05); padding: 8px; margin: 5px 0; border-left: 4px solid {$color}; font-family: monospace; font-size: 12px;'>";
        echo "<strong style='color: {$color};'>{$prefix}</strong> <span style='color: #666;'>{$timestamp}:</span> {$message}";
        echo "</div>\n";
        
        // 同时输出到HTML注释
        echo "<!-- {$prefix} {$timestamp}: {$message} -->\n";
    }
    
    /**
     * 执行SQL查询的统一方法
     * @param string $sql SQL语句
     * @param string $operation 操作类型 (select, insert, update, delete)
     * @return mixed 查询结果
     */
    private function query($sql, $operation = 'select') {
        $this->debugOutput("执行SQL: {$sql}");
        
        $result = mysqli_query($this->conn, $sql);
        
        if (!$result) {
            $error = mysqli_error($this->conn);
            $this->debugOutput("SQL执行失败: {$error}", 'error');
            return false;
        }
        
        $this->debugOutput("SQL执行成功");
        
        switch ($operation) {
            case 'select':
                return $result;
            case 'insert':
                return mysqli_insert_id($this->conn);
            case 'update':
            case 'delete':
                return mysqli_affected_rows($this->conn);
            default:
                return $result;
        }
    }
    
    /**
     * 获取单条记录
     * @param string $sql SQL语句
     * @return array|null 记录数组或null
     */
    private function getRow($sql) {
        $result = $this->query($sql);
        if ($result && mysqli_num_rows($result) > 0) {
            return mysqli_fetch_assoc($result);
        }
        return null;
    }
    
    /**
     * 获取多条记录
     * @param string $sql SQL语句
     * @return array 记录数组
     */
    public function getRows($sql) {
        $result = $this->query($sql);
        $rows = [];
        
        if ($result) {
            while ($row = mysqli_fetch_assoc($result)) {
                $rows[] = $row;
            }
        }
        
        return $rows;
    }
    
    /**
     * 字符串转义处理
     * @param string $string 要转义的字符串
     * @return string 转义后的字符串
     */
    private function escape($string) {
        return mysqli_real_escape_string($this->conn, $string);
    }
    
    // ==================== 用户相关方法 ====================
    
    /**
     * 用户登录
     * @param string $username 用户名
     * @param string $password 密码
     * @return bool 登录是否成功
     */
    public function login($username, $password) {
        $username = $this->escape($username);
        $sql = "SELECT `id`, `用户名`, `密码` FROM `用户表` WHERE `用户名` = '{$username}'";
        $user = $this->getRow($sql);
        
        if ($user && password_verify($password, $user['密码'])) {
            $_SESSION['user_id'] = $user['id'];
            $_SESSION['username'] = $user['用户名'];
            $this->debugOutput("用户 {$username} 登录成功");
            return true;
        }
        
        $this->debugOutput("用户 {$username} 登录失败", 'warning');
        return false;
    }
    
    /**
     * 用户注册
     * @param string $username 用户名
     * @param string $password 密码
     * @return bool 注册是否成功
     */
    public function register($username, $password) {
        $username = $this->escape($username);
        
        // 检查用户名是否已存在
        if ($this->getUserByUsername($username)) {
            $this->debugOutput("用户名 {$username} 已存在", 'warning');
            return false;
        }
        
        $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
        $sql = "INSERT INTO `用户表` (`用户名`, `密码`) VALUES ('{$username}', '{$hashedPassword}')";
        
        $result = $this->query($sql, 'insert');
        
        if ($result) {
            $this->debugOutput("用户 {$username} 注册成功");
            return true;
        }
        
        return false;
    }
    
    /**
     * 检查用户是否已登录
     * @return bool 是否已登录
     */
    public function isLoggedIn() {
        return isset($_SESSION['user_id']) && !empty($_SESSION['user_id']);
    }
    
    /**
     * 获取当前登录用户信息
     * @return array|null 用户信息或null
     */
    public function getCurrentUser() {
        if (!$this->isLoggedIn()) {
            return null;
        }
        
        $userId = $_SESSION['user_id'];
        $sql = "SELECT * FROM `用户表` WHERE `id` = {$userId}";
        return $this->getRow($sql);
    }
    
    /**
     * 根据用户名获取用户信息
     * @param string $username 用户名
     * @return array|null 用户信息或null
     */
    public function getUserByUsername($username) {
        $username = $this->escape($username);
        $sql = "SELECT * FROM `用户表` WHERE `用户名` = '{$username}'";
        return $this->getRow($sql);
    }
    
    /**
     * 用户退出登录
     */
    public function logout() {
        $_SESSION = [];
        session_destroy();
        $this->debugOutput("用户退出登录");
    }
    
    // ==================== 文章相关方法 ====================
    
    /**
     * 获取文章列表
     * @param int $page 页码
     * @param int $limit 每页数量
     * @param array $conditions 查询条件
     * @return array 文章列表
     */
    public function getArticles($page = 1, $limit = null, $conditions = []) {
        if ($limit === null) {
            $limit = $this->config['posts_per_page'];
        }
        
        $offset = ($page - 1) * $limit;
        $where = "1=1";
        
        // 构建查询条件
        if (!empty($conditions['category'])) {
            $category = $this->escape($conditions['category']);
            $where .= " AND a.`id` IN (
                SELECT ac.`文章ID` FROM `文章分类表` ac 
                LEFT JOIN `分类表` c ON ac.`分类ID` = c.`id` 
                WHERE c.`分类名` = '{$category}'
            )";
        }
        
        if (!empty($conditions['tag'])) {
            $tag = $this->escape($conditions['tag']);
            $where .= " AND a.`id` IN (
                SELECT at.`文章ID` FROM `文章标签表` at 
                LEFT JOIN `标签表` t ON at.`标签ID` = t.`id` 
                WHERE t.`标签名` = '{$tag}'
            )";
        }
        
        if (!empty($conditions['user_id'])) {
            $where .= " AND a.`用户ID` = " . (int)$conditions['user_id'];
        }
        
        $sql = "SELECT a.`id`, a.`标题`, a.`内容`, a.`创建时间`, a.`更新时间`, 
                       a.`阅读量`, a.`点赞量`, a.`评论量`, a.`是否置顶`, a.`是否推荐`, 
                       a.`图片`, u.`用户名`
                FROM `文章表` a 
                LEFT JOIN `用户表` u ON a.`用户ID` = u.`id`
                WHERE {$where}
                ORDER BY a.`是否置顶` DESC, a.`创建时间` DESC 
                LIMIT {$offset}, {$limit}";
        
        return $this->getRows($sql);
    }
    
    /**
     * 获取文章总数
     * @param array $conditions 查询条件
     * @return int 文章总数
     */
    public function getArticleCount($conditions = []) {
        $where = "1=1";
        
        if (!empty($conditions['user_id'])) {
            $where .= " AND `用户ID` = " . (int)$conditions['user_id'];
        }
        
        $sql = "SELECT COUNT(*) as total FROM `文章表` WHERE {$where}";
        $result = $this->getRow($sql);
        return $result ? $result['total'] : 0;
    }
    
    /**
     * 根据ID获取文章详情
     * @param int $id 文章ID
     * @return array|null 文章信息
     */
    public function getArticleById($id) {
        $id = (int)$id;
        $sql = "SELECT a.*, u.`用户名` 
                FROM `文章表` a 
                LEFT JOIN `用户表` u ON a.`用户ID` = u.`id`
                WHERE a.`id` = {$id}";
        
        return $this->getRow($sql);
    }
    
    /**
     * 发布新文章
     * @param array $data 文章数据
     * @return int|false 文章ID或false
     */
    public function publishArticle($data) {
        $this->debugOutput("开始发布文章，数据：" . print_r($data, true));
        
        // 验证必要字段
        if (empty($data['title']) || empty($data['content']) || empty($data['user_id'])) {
            $this->debugOutput("文章发布失败：缺少必要字段", 'error');
            return false;
        }
        
        $title = $this->escape($data['title']);
        $content = $this->escape($data['content']);
        $userId = (int)$data['user_id'];
        $isTop = isset($data['is_top']) ? (int)$data['is_top'] : 0;
        $isRecommend = isset($data['is_recommend']) ? (int)$data['is_recommend'] : 0;
        $image = isset($data['image']) ? $this->escape($data['image']) : '';
        
        $this->debugOutput("处理后的数据 - 标题: {$title}, 用户ID: {$userId}, 置顶: {$isTop}, 推荐: {$isRecommend}, 图片: {$image}");
        
        $sql = "INSERT INTO `文章表` (`标题`, `内容`, `用户ID`, `是否置顶`, `是否推荐`, `图片`) 
                VALUES ('{$title}', '{$content}', {$userId}, {$isTop}, {$isRecommend}, '{$image}')";
        
        $this->debugOutput("准备执行SQL: {$sql}");
        
        $articleId = $this->query($sql, 'insert');
        
        $this->debugOutput("SQL执行结果，文章ID: " . ($articleId ? $articleId : "false"));
        
        if ($articleId) {
            // 处理分类关联
            if (!empty($data['categories'])) {
                $this->debugOutput("处理分类关联: " . print_r($data['categories'], true));
                $this->updateArticleCategories($articleId, $data['categories']);
            }
            
            // 处理标签关联
            if (!empty($data['tags'])) {
                $this->debugOutput("处理标签关联: " . print_r($data['tags'], true));
                $this->updateArticleTags($articleId, $data['tags']);
            }
            
            $this->debugOutput("文章发布成功，ID: {$articleId}");
        } else {
            $this->debugOutput("文章发布失败，数据库错误: " . mysqli_error($this->conn), 'error');
        }
        
        return $articleId;
    }
    
    /**
     * 更新文章
     * @param int $id 文章ID
     * @param array $data 文章数据
     * @return bool 更新是否成功
     */
    public function updateArticle($id, $data) {
        $this->debugOutput("开始更新文章，ID: {$id}，数据：" . print_r($data, true));
        
        $id = (int)$id;
        $title = $this->escape($data['title']);
        $content = $this->escape($data['content']);
        $isTop = isset($data['is_top']) ? (int)$data['is_top'] : 0;
        $isRecommend = isset($data['is_recommend']) ? (int)$data['is_recommend'] : 0;
        $image = isset($data['image']) ? $this->escape($data['image']) : '';
        
        $sql = "UPDATE `文章表` SET 
                `标题` = '{$title}', 
                `内容` = '{$content}', 
                `是否置顶` = {$isTop}, 
                `是否推荐` = {$isRecommend}, 
                `图片` = '{$image}',
                `更新时间` = CURRENT_TIMESTAMP
                WHERE `id` = {$id}";
        
        $this->debugOutput("准备执行更新SQL: {$sql}");
        
        $result = $this->query($sql, 'update');
        
        $this->debugOutput("更新SQL执行结果: " . ($result !== false ? "成功，影响行数: {$result}" : "失败"));
        
        if ($result !== false) {
            // 更新分类关联
            if (isset($data['categories'])) {
                $this->debugOutput("更新分类关联: " . print_r($data['categories'], true));
                $this->updateArticleCategories($id, $data['categories']);
            }
            
            // 更新标签关联
            if (isset($data['tags'])) {
                $this->debugOutput("更新标签关联: " . print_r($data['tags'], true));
                $this->updateArticleTags($id, $data['tags']);
            }
            
            $this->debugOutput("文章更新成功，ID: {$id}");
            return true;
        } else {
            $this->debugOutput("文章更新失败，数据库错误: " . mysqli_error($this->conn), 'error');
        }
        
        return false;
    }
    
    /**
     * 删除文章
     * @param int $id 文章ID
     * @param int $userId 用户ID（权限检查）
     * @return bool 删除是否成功
     */
    public function deleteArticle($id, $userId) {
        $id = (int)$id;
        $userId = (int)$userId;
        
        // 检查权限
        $article = $this->getArticleById($id);
        if (!$article || $article['用户ID'] != $userId) {
            $this->debugOutput("无权限删除文章，ID: {$id}", 'warning');
            return false;
        }
        
        // 删除相关数据
        $this->query("DELETE FROM `文章分类表` WHERE `文章ID` = {$id}", 'delete');
        $this->query("DELETE FROM `文章标签表` WHERE `文章ID` = {$id}", 'delete');
        $this->query("DELETE FROM `文章评论表` WHERE `文章ID` = {$id}", 'delete');
        
        // 删除文章
        $sql = "DELETE FROM `文章表` WHERE `id` = {$id}";
        $result = $this->query($sql, 'delete');
        
        if ($result) {
            $this->debugOutput("文章删除成功，ID: {$id}");
            return true;
        }
        
        return false;
    }
    
    /**
     * 增加文章阅读量
     * @param int $id 文章ID
     */
    public function increaseViewCount($id) {
        $id = (int)$id;
        $sql = "UPDATE `文章表` SET `阅读量` = `阅读量` + 1 WHERE `id` = {$id}";
        $this->query($sql, 'update');
    }
    
    /**
     * 文章点赞
     * @param int $id 文章ID
     * @return bool 点赞是否成功
     */
    public function likeArticle($id) {
        $id = (int)$id;
        $sql = "UPDATE `文章表` SET `点赞量` = `点赞量` + 1 WHERE `id` = {$id}";
        $result = $this->query($sql, 'update');
        
        if ($result) {
            $this->debugOutput("文章点赞成功，ID: {$id}");
            return true;
        }
        
        return false;
    }
    
    // ==================== 分类相关方法 ====================
    
    /**
     * 获取所有分类
     * @return array 分类列表
     */
    public function getCategories() {
        $sql = "SELECT * FROM `分类表` ORDER BY `分类排序`, `id`";
        return $this->getRows($sql);
    }
    
    /**
     * 获取文章的分类
     * @param int $articleId 文章ID
     * @return array 分类列表
     */
    public function getArticleCategories($articleId) {
        $articleId = (int)$articleId;
        $sql = "SELECT c.* 
                FROM `文章分类表` ac 
                LEFT JOIN `分类表` c ON ac.`分类ID` = c.`id`
                WHERE ac.`文章ID` = {$articleId}
                ORDER BY c.`分类排序`";
        
        return $this->getRows($sql);
    }
    
    /**
     * 更新文章分类关联
     * @param int $articleId 文章ID
     * @param array $categoryIds 分类ID数组
     */
    private function updateArticleCategories($articleId, $categoryIds) {
        $articleId = (int)$articleId;
        
        // 删除旧关联
        $this->query("DELETE FROM `文章分类表` WHERE `文章ID` = {$articleId}", 'delete');
        
        // 插入新关联
        foreach ($categoryIds as $categoryId) {
            $categoryId = (int)$categoryId;
            $sql = "INSERT INTO `文章分类表` (`文章ID`, `分类ID`) VALUES ({$articleId}, {$categoryId})";
            $this->query($sql, 'insert');
        }
    }
    
    // ==================== 标签相关方法 ====================
    
    /**
     * 获取所有标签
     * @return array 标签列表
     */
    public function getTags() {
        $sql = "SELECT * FROM `标签表` ORDER BY `标签排序`, `id`";
        return $this->getRows($sql);
    }
    
    /**
     * 获取文章的标签
     * @param int $articleId 文章ID
     * @return array 标签列表
     */
    public function getArticleTags($articleId) {
        $articleId = (int)$articleId;
        $sql = "SELECT t.* 
                FROM `文章标签表` at 
                LEFT JOIN `标签表` t ON at.`标签ID` = t.`id`
                WHERE at.`文章ID` = {$articleId}
                ORDER BY t.`标签排序`";
        
        return $this->getRows($sql);
    }
    
    /**
     * 更新文章标签关联
     * @param int $articleId 文章ID
     * @param array $tagIds 标签ID数组
     */
    private function updateArticleTags($articleId, $tagIds) {
        $articleId = (int)$articleId;
        
        // 删除旧关联
        $this->query("DELETE FROM `文章标签表` WHERE `文章ID` = {$articleId}", 'delete');
        
        // 插入新关联
        foreach ($tagIds as $tagId) {
            $tagId = (int)$tagId;
            $sql = "INSERT INTO `文章标签表` (`文章ID`, `标签ID`) VALUES ({$articleId}, {$tagId})";
            $this->query($sql, 'insert');
        }
    }
    
    // ==================== 评论相关方法 ====================
    
    /**
     * 获取文章评论
     * @param int $articleId 文章ID
     * @return array 评论列表
     */
    public function getComments($articleId) {
        $articleId = (int)$articleId;
        $sql = "SELECT c.`id` as comment_id, c.`评论内容`, c.`评论时间`, 
                       c.`评论用户ID`, u.`用户名`
                FROM `文章评论表` ac 
                LEFT JOIN `评论表` c ON ac.`评论ID` = c.`id`
                LEFT JOIN `用户表` u ON c.`评论用户ID` = u.`id`
                WHERE ac.`文章ID` = {$articleId}
                ORDER BY c.`评论时间` DESC";
        
        return $this->getRows($sql);
    }
    
    /**
     * 发布评论
     * @param int $articleId 文章ID
     * @param int $userId 用户ID
     * @param string $content 评论内容
     * @return bool 发布是否成功
     */
    public function publishComment($articleId, $userId, $content) {
        $articleId = (int)$articleId;
        $userId = (int)$userId;
        $content = $this->escape($content);
        
        // 插入评论
        $sql = "INSERT INTO `评论表` (`评论内容`, `评论用户ID`) VALUES ('{$content}', {$userId})";
        $commentId = $this->query($sql, 'insert');
        
        if ($commentId) {
            // 建立文章评论关联
            $sql = "INSERT INTO `文章评论表` (`文章ID`, `评论ID`) VALUES ({$articleId}, {$commentId})";
            $result = $this->query($sql, 'insert');
            
            if ($result !== false) {
                // 重新计算并更新文章评论数量（避免累积错误）
                $countSql = "SELECT COUNT(*) as count FROM `文章评论表` WHERE `文章ID` = {$articleId}";
                $countResult = $this->getRow($countSql);
                $actualCount = $countResult['count'];
                
                $this->query("UPDATE `文章表` SET `评论量` = {$actualCount} WHERE `id` = {$articleId}", 'update');
                $this->debugOutput("评论发布成功，文章ID: {$articleId}，当前评论数: {$actualCount}");
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 删除评论
     * @param int $commentId 评论ID
     * @param int $userId 用户ID（权限检查）
     * @return bool 删除是否成功
     */
    public function deleteComment($commentId, $userId) {
        $commentId = (int)$commentId;
        $userId = (int)$userId;
        
        // 检查权限（评论作者或文章作者可以删除）
        $sql = "SELECT c.`评论用户ID`, ac.`文章ID`, a.`用户ID` as article_author
                FROM `评论表` c
                LEFT JOIN `文章评论表` ac ON c.`id` = ac.`评论ID`
                LEFT JOIN `文章表` a ON ac.`文章ID` = a.`id`
                WHERE c.`id` = {$commentId}";
        
        $comment = $this->getRow($sql);
        
        if (!$comment || ($comment['评论用户ID'] != $userId && $comment['article_author'] != $userId)) {
            $this->debugOutput("无权限删除评论，ID: {$commentId}", 'warning');
            return false;
        }
        
        // 删除评论关联
        $this->query("DELETE FROM `文章评论表` WHERE `评论ID` = {$commentId}", 'delete');
        
        // 删除评论
        $result = $this->query("DELETE FROM `评论表` WHERE `id` = {$commentId}", 'delete');
        
        if ($result) {
            // 重新计算并更新文章评论数量（避免累积错误）
            $articleId = $comment['文章ID'];
            $countSql = "SELECT COUNT(*) as count FROM `文章评论表` WHERE `文章ID` = {$articleId}";
            $countResult = $this->getRow($countSql);
            $actualCount = $countResult['count'];
            
            $this->query("UPDATE `文章表` SET `评论量` = {$actualCount} WHERE `id` = {$articleId}", 'update');
            $this->debugOutput("评论删除成功，ID: {$commentId}，当前评论数: {$actualCount}");
            return true;
        }
        
        return false;
    }
    
    /**
     * 编辑评论
     * @param int $commentId 评论ID
     * @param int $userId 用户ID（权限检查）
     * @param string $content 新的评论内容
     * @return bool 编辑是否成功
     */
    public function updateComment($commentId, $userId, $content) {
        $commentId = (int)$commentId;
        $userId = (int)$userId;
        $content = $this->escape($content);
        
        $this->debugOutput("开始编辑评论，ID: {$commentId}，用户ID: {$userId}，新内容: {$content}");
        
        // 检查评论是否属于当前用户
        $sql = "SELECT `评论用户ID` FROM `评论表` WHERE `id` = {$commentId}";
        $comment = $this->getRow($sql);
        
        if (!$comment || $comment['评论用户ID'] != $userId) {
            $this->debugOutput("无权限编辑评论，ID: {$commentId}", 'warning');
            return false;
        }
        
        // 更新评论内容
        $sql = "UPDATE `评论表` SET `评论内容` = '{$content}' WHERE `id` = {$commentId} AND `评论用户ID` = {$userId}";
        $result = $this->query($sql, 'update');
        
        if ($result !== false) {
            $this->debugOutput("评论编辑成功，ID: {$commentId}");
            return true;
        } else {
            $this->debugOutput("评论编辑失败，数据库错误: " . mysqli_error($this->conn), 'error');
        }
        
        return false;
    }
    
    // ==================== 统计相关方法 ====================
    
    /**
     * 获取统计数据
     * @return array 统计数据
     */
    public function getStats() {
        $stats = [];
        
        // 用户总数
        $result = $this->getRow("SELECT COUNT(*) as total FROM `用户表`");
        $stats['total_users'] = $result['total'];
        
        // 文章总数
        $result = $this->getRow("SELECT COUNT(*) as total FROM `文章表`");
        $stats['total_articles'] = $result['total'];
        
        // 评论总数
        $result = $this->getRow("SELECT COUNT(*) as total FROM `评论表`");
        $stats['total_comments'] = $result['total'];
        
        // 总阅读量
        $result = $this->getRow("SELECT SUM(`阅读量`) as total FROM `文章表`");
        $stats['total_views'] = $result['total'] ?: 0;
        
        // 总点赞量
        $result = $this->getRow("SELECT SUM(`点赞量`) as total FROM `文章表`");
        $stats['total_likes'] = $result['total'] ?: 0;
        
        return $stats;
    }
    
    // ==================== 工具方法 ====================
    
    /**
     * 页面重定向
     * @param string $url 重定向地址
     */
    public function redirect($url) {
        header("Location: {$url}");
        exit();
    }
    
    /**
     * HTML转义
     * @param string $string 要转义的字符串
     * @return string 转义后的字符串
     */
    public function htmlEscape($string) {
        // 如果不是字符串，先转换为字符串
        if (!is_string($string)) {
            if (is_array($string)) {
                $this->debugOutput("警告：尝试转义数组，已转换为JSON字符串", 'warning');
                $string = json_encode($string, JSON_UNESCAPED_UNICODE);
            } else {
                $string = (string)$string;
            }
        }
        return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
    }
    
    /**
     * 格式化日期
     * @param string $datetime 日期时间
     * @param string $format 格式
     * @return string 格式化后的日期
     */
    public function formatDate($datetime, $format = 'Y-m-d H:i') {
        return date($format, strtotime($datetime));
    }
    
    /**
     * 生成文章摘要
     * @param string $content 文章内容
     * @param int $length 摘要长度
     * @return string 文章摘要
     */
    public function getExcerpt($content, $length = 200) {
        $content = strip_tags($content);
        if (mb_strlen($content, 'UTF-8') <= $length) {
            return $content;
        }
        return mb_substr($content, 0, $length, 'UTF-8') . '...';
    }
    
    /**
     * 获取配置值
     * @param string $key 配置键
     * @return mixed 配置值
     */
    public function getConfig($key) {
        return isset($this->config[$key]) ? $this->config[$key] : null;
    }
    
    /**
     * 设置调试模式
     * @param bool $debug 是否开启调试
     */
    public function setDebug($debug) {
        $this->debug = $debug;
    }
    
    /**
     * 图片上传处理函数
     * 保存到项目根目录的uploads文件夹
     * @param array $file 上传的文件信息($_FILES中的某个文件)
     * @return array 上传结果 ['success' => true/false, 'path' => '路径', 'error' => '错误信息']
     */
    public function uploadImage($file) {
        // 检查是否有上传文件
        if (!isset($file) || $file['error'] === UPLOAD_ERR_NO_FILE) {
            return ['success' => false, 'error' => '没有选择文件'];
        }
        
        // 检查上传是否有错误
        if ($file['error'] !== UPLOAD_ERR_OK) {
            return ['success' => false, 'error' => '文件上传出错，错误代码：' . $file['error']];
        }
        
        // 上传目录设置为项目根目录下的uploads/images/年/月/
        // 获取项目根目录的绝对路径
        $projectRoot = dirname(dirname(__FILE__)); // 从includes目录回到项目根目录
        $uploadDir = $projectRoot . '/uploads/images/' . date('Y/m') . '/';
        
        // 创建目录（如果不存在）
        if (!is_dir($uploadDir)) {
            if (!mkdir($uploadDir, 0755, true)) {
                return ['success' => false, 'error' => '无法创建上传目录'];
            }
        }
        
        // 检查文件类型（只允许图片格式）
        $allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/jpg'];
        if (!in_array($file['type'], $allowedTypes)) {
            return ['success' => false, 'error' => '只支持JPG、PNG、GIF格式的图片'];
        }
        
        // 检查文件大小（使用配置中的最大上传大小）
        if ($file['size'] > $this->config['max_upload_size']) {
            $maxSizeMB = round($this->config['max_upload_size'] / 1024 / 1024, 1);
            return ['success' => false, 'error' => "图片大小不能超过{$maxSizeMB}MB"];
        }
        
        // 生成唯一的文件名（防止重复）
        $extension = pathinfo($file['name'], PATHINFO_EXTENSION);
        $filename = 'img_' . time() . '_' . rand(1000, 9999) . '.' . $extension;
        $uploadPath = $uploadDir . $filename;
        
        // 移动上传的文件到目标目录
        if (move_uploaded_file($file['tmp_name'], $uploadPath)) {
            // 返回相对于网站根目录的路径
            $relativePath = 'uploads/images/' . date('Y/m') . '/' . $filename;
            $this->debugOutput("图片上传成功：{$relativePath}");
            return ['success' => true, 'path' => $relativePath];
        } else {
            return ['success' => false, 'error' => '文件移动失败'];
        }
    }
    
    /**
     * 析构函数 - 关闭数据库连接
     */
    public function __destruct() {
        if ($this->conn) {
            mysqli_close($this->conn);
            $this->debugOutput("数据库连接已关闭");
        }
    }
} 